package com.john.blockchain.demo.first;

import com.john.common.util.DateUtil;
import com.john.common.util.RandomStrings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author jiangguangtao 2018/4/14
 */
public class HashCalcApp {
    private static final Logger LOGGER = LoggerFactory.getLogger(HashCalcApp.class);

    public static void main(String[] args) {
        int taskRunners = Runtime.getRuntime().availableProcessors();
        CountDownLatch latch = new CountDownLatch(taskRunners);
        ArrayBlockingQueue<String> nonceQueue = new ArrayBlockingQueue<String>(50);

        String originStr = RandomStrings.randomAlphabet(32);
        LOGGER.info("待计算Hash字符串：{}", originStr);
        HashCalcTaskContext context = new HashCalcTaskContext(latch, nonceQueue, originStr);
        context.setMatchCodeLength(7); // 计算次数：59645284, 用时：00:01:46.037
//        context.setMatchCodeLength(8); // 计算次数：2072745969, 用时：00:45:33.691

        ExecutorService executor = Executors.newFixedThreadPool(taskRunners + 1);

        // 首先启动随机数生成线程
        LOGGER.info("启动随机数生成线程");
        executor.submit(new HashNonceGeneratorTask(context, RandomStrings.random(4), 20));
        long beginTime = System.currentTimeMillis();

        for (int i = 0; i < taskRunners; i++) {
            LOGGER.info("启动计算线程{}", i);
            executor.submit(new HashCalcTask(context));
        }

        try {
            LOGGER.info("等待计算任务结束");
            latch.await();
        } catch (InterruptedException e) {
            LOGGER.warn("等待计算任务中断异常 {}", e);
        }
        long durations = System.currentTimeMillis() - beginTime;

        LOGGER.info("计算结束 结果：{},计算次数：{}, 用时：{}", context.getResultHash(), context.getCalcTimes(), DateUtil.formatTimeDurationMilliSeconds(durations));
        executor.shutdown();

//        try {
//            LOGGER.info("按回车键结束。。。");
//            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//            reader.readLine();
//        } catch (IOException e) {
//            LOGGER.error("读取结束符异常");
//        }
    }
}
